#include "reflect/ClassFactory.h"

#include <assert.h>

ClassObject* ClassFactory::getClass(const std::string& classname)
{
    auto it = ClassMap.find(classname);
    if (it == ClassMap.end()) {
        return nullptr;
    }

    return it->second();
}

void ClassFactory::registerClass(const std::string& classname,
                                 FactoryClass       classobject)
{
    ClassMap[classname] = classobject;
}

void ClassFactory::registerClassField(const std::string& classname,
                                      const std::string& name,
                                      const std::string& type,
                                      size_t             offset)
{
    assert(getClass(classname) != nullptr);

    ClassFieldMap[classname].push_back(new (std::nothrow)
                                           ClassField(name, type, offset));
}

int ClassFactory::getClassCount()
{
    return ClassMap.size();
}

int ClassFactory::getClassFieldCount(const std::string& classname)
{
    return ClassFieldMap[classname].size();
}

ClassField* ClassFactory::getClassField(const std::string& classname,
                                        const std::string& fieldname)
{
    auto fields = ClassFieldMap[classname];
    for (auto it : fields) {
        if (it->name() == fieldname) {
            return it;
        }
    }

    return nullptr;
}

ClassField* ClassFactory::getClassField(const std::string& classname, int pos)
{
    auto fields = ClassFieldMap[classname];
    if (pos < 0 || pos >= (int)fields.size()) {
        return nullptr;
    }

    return fields[pos];
}

void ClassFactory::registerClassMethod(const std::string& classname,
                                       const std::string& methodname,
                                       uintptr_t          method)
{
    ClassMethodMap[classname].push_back(new (std::nothrow)
                                            ClassMethod(methodname, method));
}

ClassMethod* ClassFactory::getClassMethod(const std::string& classname,
                                          const std::string& methodname)
{
    auto it = ClassMethodMap[classname];
    for (auto i : it) {
        if (i->name() == methodname) {
            return i;
        }
    }

    return nullptr;
}

ClassMethod* ClassFactory::getClassMethod(const std::string& classname, int pos)
{
    auto it = ClassMethodMap[classname];
    int i = (int)(it.size());
    if (pos < 0 || pos >= (int)(it.size())) {
        return nullptr;
    }
    return it[pos];
}
